﻿/* Muaz Khan – http://dashingquill.web.officelive.com */

/***********************************
* Handling stuff on user-page! or homepage [Tweets, Follow, Edit/Delete, Share and more...]
***********************************/

var user = window.user || {};
user = (function () {
    /***********************************
    * Caching the global object: dashingquill
    ***********************************/
    var dq = dashingquill;

    /***********************************
    * Host name - for handling relative URL issues
    ***********************************/
    var dname = dq.domainName;

    /***********************************
    * Sizzle library (using for cross-browser advance DOM search)
    ***********************************/
    var sz = Sizzle;

    /***********************************
    * Adding new tweet
    ***********************************/
    var newTweet = function () {
        dq.bind('#tweet-button', 'click', function () {            
            /***********************************
            * First of all, tracking the circles/users to share the post! Same like Google+!!
            ***********************************/
            var names = sz('.circle-name-to-share');

            var circleNames = '';
            dq.each(names, function (circle) {
                circleNames += circle.getAttribute('accesskey') + ',';
            });

            names = sz('.user-name-to-share');

            var userNames = '';
            dq.each(names, function (user) {
                userNames += user.getAttribute('accesskey') + ',';
            });

            var tweetMessage = sz('#tweetMessage')[0];
            if (tweetMessage.value.length <= 0) {
                tweetMessage.focus();
                return;
            }

            var data = '?message=' + dq.validate(tweetMessage.value);

            if (circleNames.length <= 0 && userNames.length > 0)
                data += '&circles=NoCircle&users=' + userNames;
            else {
                if (circleNames.length <= 0 || circleNames.indexOf('Public') != -1)
                    data += '&circles=Public';
                else if (circleNames.length > 0)
                    data += '&circles=' + circleNames;

                if (userNames.length > 0)
                    data += '&users=' + userNames;
                else data += '&users=NoUser';
            }

            tweetMessage.value = ''; /* Removing the content of tweet box. No more needed!! */

            /***********************************
            * XMLHttpRequest to add new post
            ***********************************/
            dq.xhr({
                url: dname + '/NewTweet' + data,
                callback: function (tweet) {
                    if (tweet.IsSuccess == true) {
                        var tweetContainer = dq.find('#tweets-container');
                        var tweetSection = document.createElement('div');
                        var gravatarImage = dq.find('#gravatar-image');
                        var tweetString = '<div class="user-image"><img src="' + gravatarImage.src + '" itemprop="image" width="60" height="60" /></div>'
                            + '<div class="tweet-section"><div class="manage-tweet"></div><h2 class="name-section">'
                                + '<a href="' + dname + '/' + tweet.userToken + '">' + tweet.fullName + '</a> - <a href="' + dname + '/' + tweet.tweetToken + '/' + tweet.postUrl + '">'
                                    + '<span class="time"><time class="time" itemprop="date" datetime="' + tweet.machineTime + '" pubdate>' + tweet.tweetingTime + '</time></span></a></h2>'
                                        + '<div class="tweet-message">' + tweet.message + '</div></div>';
                        tweetSection.innerHTML = tweetString;
                        dq.prepend(tweetContainer, tweetSection);
                    }
                    else {
                        alert(tweet.Error);
                    }
                }
            });
        });
    };

    /***********************************
    * Handling actions on a specific post; i.e. Edit/Delete/ or Link
    ***********************************/
    var postOptions = function () {
        dq.bind('.manage-tweet', 'click', function (option, e) {
            dq.stopBubbling(e);

            var postOption = dq.find('#post-options', option.parentNode);
            dq.show(postOption);

            /***********************************
            * Only the post owner can EDIT/DELET
            ***********************************/
            var owner = dq.find('#owner', option.parentNode).value == 'owner';
            if (owner) postOption.innerHTML = '<div id="edit-post" class="edit-post">Edit this post</div>'
                                    + '<div id="delete-post" class="delete-post">Delete this post</div>'
                                    + '<div id="linkTo-post" class="linkTo-post">Link to this post</div>';
            else postOption.innerHTML = '<div id="linkTo-post" class="linkTo-post">Link to this post</div>';

            /***********************************
            * Handling Link-To Post event
            ***********************************/
            dq.bind('.linkTo-post', 'click', function () {
                window.location = sz('.p-Link', postOption.parentNode)[0].href;
            });

            /***********************************
            * Handling DELETE Post event
            ***********************************/
            dq.bind('.delete-post', 'click', function () {
                postOption.style.marginLeft = '595px';
                postOption.innerHTML = '<p style="padding:10px;">Are you agreeing to permanently delete this post?</p>'
                                    + '<p style="margin: 8px;margin-bottom: 12px;"><span class="delete-agree red-button">Delete permanently</span>'
                                    + '<span class="cancel-delete">Cancel</span></p>';
                dq.once(2, function () {
                    dq.show(postOption);
                });

                var cancelDelete = dq.find('.cancel-delete', postOption);
                dq.bind(cancelDelete, 'click', function () {
                    dq.hide(postOption);
                    postOption.style.marginLeft = '782px';
                });

                var deleteAgree = dq.find('.delete-agree', postOption);
                dq.bind(deleteAgree, 'click', function () {
                    var id = postOption.parentNode.id;
                    dq.xhr({
                        url: dname + '/DeletePost/' + id,
                        callback: function (response) {
                            if (response == true) {
                                var post = dq.find('#' + id).parentNode;
                                post.style.opacity = '0';
                                dq.once(8, function () {
                                    post.parentNode.removeChild(post);
                                });
                            }
                            else alert(response);
                            postOption.style.marginLeft = '782px';
                        }
                    });
                });
            });

            /***********************************
            * Handling Edit Post event
            ***********************************/
            dq.bind('.edit-post', 'click', function () {
                var id = postOption.parentNode.id;
                dq.xhr({
                    url: dname + '/GetForEdit/' + id,
                    callback: function (response) {
                        if (response.IsSuccess == true) {
                            var tweetMessage = dq.find('.tweet-message', postOption.parentNode)[0];
                            var innerHtml = tweetMessage.innerHTML;
                            tweetMessage.innerHTML = '<textarea style="width: 850px;border:1px solid #D7D7D7;">' + response.tweetMessage + '</textarea>';

                            tweetMessage.innerHTML += '<div style="margin-top: 5px;">'
                            + '<div class="submit-changes blue-button">Save</div>'
                            + '<div class="cancel-edit">Cancel</div>'
                            + '</div>';

                            var submitButton = dq.find('.submit-changes', tweetMessage)[0];
                            var textarea = dq.find('textarea', tweetMessage)[0];

                            dq.bind(submitButton, 'click', function () {
                                dq.xhr({
                                    url: dname + '/SubmitChanges?id=' + id + '&tweetMessage=' + dq.validate(textarea.value),
                                    callback: function (result) {
                                        if (result.IsSuccess == true) {
                                            tweetMessage.innerHTML = result.tweetMessage;
                                        }
                                        else alert(result.Error);
                                    }
                                });
                            });

                            var canceltButton = dq.find('.cancel-edit', tweetMessage)[0];
                            dq.bind(canceltButton, 'click', function () {
                                tweetMessage.innerHTML = innerHtml;
                            });

                            expand(textarea); /* calling at the end; because it throws error in IE and stops further code execution */
                        }
                        else alert(response.Error);
                    }
                });
            });

        });
    };
        
    /***********************************
    * Handling textarea auto expand!
    ***********************************/
    var expand = function (elemeToExpand) {
        var interval;

        function getStyle(el, style) {
            var value = el.style[toCamelCase(style)];

            if (!value)
                if (document.defaultView)
                    value = document.defaultView.getComputedStyle(el, "").getPropertyValue(style);

                else if (el.currentStyle)
                    value = el.currentStyle[toCamelCase(style)];

            if (value.length > 0) {
                value = ((value.charAt(value.length - 1, 1) == "x") ? parseInt(value.substring(0, value.length - 2)) : value);
            }
            return value;
        }
        function toCamelCase(sInput) {
            var oStringList = sInput.split('-');
            if (oStringList.length == 1)
                return oStringList[0];
            var ret = sInput.indexOf("-") == 0 ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) : oStringList[0];
            for (var i = 1, len = oStringList.length; i < len; i++) {
                var s = oStringList[i];
                ret += s.charAt(0).toUpperCase() + s.substring(1);
            }
            return ret;
        }

        var autoExpand = function (t) {
            var textarea = t;
            var minHeight = textarea.offsetHeight;
            var a = parseInt(getStyle(textarea, 'min-height'));
            if (a > 0) minHeight = a;

            // adjust the textarea
            textarea.style.overflow = 'hidden';
            textarea.style.overflowX = 'auto';
            // set the width and height to the correct values
            textarea.style.width = getStyle(textarea, 'width') + 'px';
            textarea.style.height = getStyle(textarea, 'height') + 'px';

            // create a new element that will be used to track the dimensions
            var dummyId = Math.floor(Math.random() * 99999) + '_dummy';
            var div = document.createElement('div');
            div.setAttribute('id', dummyId);
            document.body.appendChild(div);
            var dummy = document.getElementById(dummyId);

            // match the new elements style to the textarea
            dummy.style.fontFamily = getStyle(textarea, 'font-family');
            dummy.style.fontWeight = getStyle(textarea, 'font-weight');
            dummy.style.fontSize = getStyle(textarea, 'font-size') + 'px';
            dummy.style.width = getStyle(textarea, 'width') + 'px';
            dummy.style.padding = getStyle(textarea, 'padding') + 'px';
            dummy.style.margin = getStyle(textarea, 'margin') + 'px';
            dummy.style.overflowX = 'auto';
            // hide the created div away
            dummy.style.position = 'absolute';
            dummy.style.top = '0px';
            dummy.style.left = '-9999px';
            dummy.innerHTML = '&nbsp;42';

            var lineHeight = dummy.offsetHeight;
            var checkExpand = function () {
                var html = textarea.value;
                html = html.replace(/\n/g, '<br>new');
                if (dummy.innerHTML != html) {
                    dummy.innerHTML = html;
                    var dummyHeight = dummy.offsetHeight;
                    var textareaHeight = textarea.offsetHeight;
                    if (textareaHeight != dummyHeight) {
                        if (dummyHeight > minHeight) {
                            textarea.style.height = (dummyHeight + lineHeight) + 'px';
                        }
                        else {
                            textarea.style.height = minHeight + 'px';
                        }
                    }
                }
            };
            dq.bind(textarea, 'focus', function () {
                interval = window.setInterval(function () { checkExpand(); }, 500);
            });

            dq.bind(textarea, 'blur', function () {
                clearInterval(interval);
            });

            checkExpand();
        };
        autoExpand(elemeToExpand);
    };

    /***********************************
    * Current user's about section
    ***********************************/
    var menuClick = function () {
        /***********************************
        * On "username" click [left-side of top menus-section] - displaying user's about section
        ***********************************/
        dq.bind('#username', 'click', function () {
            dq.show('#about-user');
        });

        var you = dq.find('#you');
        if (you) {
            dq.bind(you, 'click', function () {
                location = dname + '/' + you.getAttribute('accesskey');
            });
        }

        /***********************************
        * Stopping Bubbling of the events!!
        ***********************************/
        dq.bind('#about-user', 'click', function (aboutUser, e) {
            dq.stopBubbling(e);
            dq.show(aboutUser);
        });

        /***********************************
        * On "Add to circle" button click
        ***********************************/
        dq.bind('#follow-user', 'click', function () {
            dq.show('#circles-context-menu');
        });

        dq.bind('#circles-context-menu', 'click', function (circlesContextMneu) {
            dq.show(circlesContextMneu);
        });

            /***********************************
        * Same like Google+, new circles can be created in-place
        ***********************************/
        dq.bind('#create-circle', 'click', function (circle) {
            dq.find('#circles-context-menu').style.marginLeft = '266px';

            dq.show('#create-circle-p');
            dq.find('#circle-name-text').focus();
            dq.hide(circle);
            dq.hide('#no-circle');
        });

        /***********************************
        * Creating the new circle
        ***********************************/
        dq.bind('#create-circle-now', 'click', function (btn) {
            var textbox = dq.find('#circle-name-text');

            if (textbox.value.length <= 0) {
                textbox.style.border = '1px solid red';
                btn.className += ' red-button';
                return;
            }
            else {
                btn.className = btn.className.replace(' red-button', '');
                textbox.style.border = '1px solid #4D90FE';
            }

            dq.show('#create-circle');

            var circle = document.createElement('div');
            circle.className = 'circle-name in-circle';
            var circleName = textbox.value;
            circle.innerHTML = '<div style="float: right;">1</div><div>' + circleName + '</div>';
            textbox.value = '';
            dq.find('#circles-list').appendChild(circle);
            dq.hide('#create-circle-p');

            dq.xhr({
                url: '/CreateCircle/' + circleName + '/' + dq.find('#user-token').value,
                callback: function (response) {                    
                    if (response.IsSuccess == false) {
                        dq.find('#circles-list').removeChild(circle);
                        alert(response.Error);                        
                    }
                    else {
                        circleListItemClick();

                        var followUser = dq.find('#follow-user');
                        if (followUser) {
                            followUser.className += ' green-button';
                            sz('span', followUser)[0].innerHTML = 'In your circles';
                            followUser.className = followUser.className.replace(/red-button/g, '');
                        }
                    }
                    dq.find('#circles-context-menu').style.marginLeft = '380px';
                }
            });
        });

        circleListItemClick();
    };
        
    /***********************************
    * Same like Google+, circle/uncircle the user with just one click on the circle name!
    ***********************************/
    var circleListItemClick = function () {
        dq.bind(sz('#circles-list .circle-name'), 'click', function (c) {
            var div = sz('.circleName', c)[0];

            /***********************************
            * If user is in-circle, making it out-of-circle; otherwise circling that user
            ***********************************/
            dq.xhr({
                url: dname + '/InOrOutFromCircle/' + div.innerHTML + '/' + dq.find('#user-token').value,
                callback: function (response) {                    
                    if (response.IsSuccess == false) alert(response.Error);
                    else {
                        var followUser = dq.find('#follow-user');
                        if (response.InCircle == true) {
                            div.parentNode.className += ' in-circle';

                            div.style.color = 'White';
                            sz('.circleMembersCount', div.parentNode)[0].style.color = 'White';

                            var mCount = sz('.circleMembersCount', div.parentNode)[0];
                            mCount.innerHTML = (+mCount.innerHTML) + 1;
                            
                            if (followUser && response.FoundInAnyCircle == true) {
                                followUser.className += ' green-button';
                                sz('span', followUser)[0].innerHTML = 'In your circles';
                                followUser.className = followUser.className.replace(/red-button/g, '');
                            }                            
                        }
                        else {
                            div.parentNode.className = 'circle-name';

                            div.style.color = 'Black';
                            sz('.circleMembersCount', div.parentNode)[0].style.color = 'Black';

                            var mCount = sz('.circleMembersCount', div.parentNode)[0];
                            if (mCount.innerHTML != '0') mCount.innerHTML = (+mCount.innerHTML) - 1;

                            if (followUser) {
                                if (response.FoundInAnyCircle == false) {                                    
                                    followUser.className += ' red-button';                                    
                                    sz('span', followUser)[0].innerHTML = 'Not in your circles';
                                    followUser.className = followUser.className.replace(/green-button/g, '');
                                }                                
                            }
                        }
                    }
                    mouseoverEvents();
                }
            });
        });
    };

    /***********************************
    * Add circles names or users to share the post
    ***********************************/
    var addMoreClick = function () {
        dq.bind('#add-more', 'click', function (addMoreBtn) {
            addMoreBtn.innerHTML = '<input id="add-more-text" class="add-more-text" type=text style="background-color: transparent;" />';
            addMoreBtn.style.padding = '0';
            var addMoreText = dq.find('#add-more-text');
            addMoreText.focus();
                        
            /***********************************
            * Same like Google+, user can not only share to circles but also they can share to individual users or more than one user too!!
            ***********************************/
            dq.bind(addMoreText, 'keyup', function (elem, e) {
                /***********************************
                * Circle-Name or User-Name or Email has been added; on Enter key (Same like Google+) we have to track relative users or circles
                ***********************************/
                if (e.keyCode == 13) {
                    var shareToResult = dq.find('#share-to-result');

                    /***********************************
                    * Suppose a username or email was entered (Same like Google+) - Getting that value
                    ***********************************/
                    var value = elem.value;

                    /***********************************
                    * Validating username entered; if exists; auto-inserting that user's fullName + userToken
                    ***********************************/
                    dq.xhr({
                        url: dname + '/ValidatecircleOrUser/' + value,
                        callback: function (response) {
                            if (response.IsSuccess == false) alert(response.Error);
                            else {
                                var div = document.createElement('div');

                                if (response.IsCircle == true) {
                                    div.className = 'circle-name-to-share';
                                    div.setAttribute('accesskey', response.CircleToken);
                                    div.innerHTML = response.CircleName + '<img class="remove-circle-name" src="' + dname + '/content/images/close-dim.png" style="margin-left: 5px; margin-right: -5px;" />';
                                }
                                else if (response.IsUser == true) {
                                    div.className = 'user-name-to-share';
                                    div.setAttribute('accesskey', response.UserToken);
                                    div.innerHTML = response.UserFullName + '<img class="remove-circle-name" src="' + dname + '/content/images/close-dim.png" style="margin-left: 5px; margin-right: -5px;" />';
                                }
                                else {
                                    alert('No circle; no user!');
                                    return;
                                }

                                shareToResult.appendChild(div);
                                elem.value = '';

                                removecircleEvents(div);
                            }
                        }
                    });
                }
            });
            dq.show('#share-to');
        });
        shareToListClick();
    };
    
    /***********************************
    * User's clicks for circle names to share the post!!
    ***********************************/
    var shareToListClick = function () {
        dq.bind(sz('#share-to div'), 'click', function (elem) {
            var shareToResult = dq.find('#share-to-result');
            var div = document.createElement('div');
            var circleName = elem.getAttribute('accesskey');
            div.innerHTML = circleName + '<img class="remove-circle-name" src="' + dname + '/content/images/close-dim.png" style="margin-left: 5px; margin-right: -5px;" />';

            if (elem.id != 'Public') div.setAttribute('accesskey', elem.id);
            else div.setAttribute('accesskey', 'Public');

            div.className = 'circle-name-to-share';
            if (circleName == 'Public') div.style.color = 'Green';
            shareToResult.appendChild(div);
            elem.parentNode.removeChild(elem);
            removecircleEvents(div);
            dq.show('#share-to');
        });
    };
    
    /***********************************
    * User can remove circle or user (for sharing post) [Same like Google+]
    ***********************************/
    var removecircleEvents = function (parent) {

        dq.bind('.remove-circle-name', 'mouseover', function (closeButton) {
            closeButton.src = dname + '/content/images/close-black.png';
        });

        dq.bind('.remove-circle-name', 'mouseout', function (closeButton) {
            closeButton.src = dname + '/content/images/close-dim.png';
        });

        dq.bind(sz('.remove-circle-name', parent)[0], 'click', function (closeButton) {
            /*dq.find('#share-to').innerHTML += '<div class="circle-name" accesskey="' + circleName + '">' + circleName + ' <span>(-)</span></div>';*/
            closeButton.parentNode.parentNode.removeChild(closeButton.parentNode);
            shareToListClick();
        });
    };
    
    /***********************************
    * Sometimes, CSS don't help us do everything; so we've to use JavaScript instead for presentation logic!!
    ***********************************/
    var mouseoverEvents = function () {        
        /***********************************
        * List for circle/uncircle a user - or - create new circle - in the *about* section on the user-page [UserPage.cshtml]
        ***********************************/
        dq.bind(sz('#circles-list div'), 'mouseover', function (div) {            
            var divs = sz('div', div);
            dq.each(divs, function (d) {
                d.style.color = 'White';
            });
        });
        dq.bind(sz('#circles-list .circle-name:not(.in-circle)'), 'mouseout', function (div) {
            var divs = sz('div', div);
            dq.each(divs, function (d) {
                d.style.color = 'Black';
            });
        });        
        
        /***********************************
        * "Add to circle" button - in the "about" section - on user-page [UserPage.cshtml]
        ***********************************/
        dq.bind('#follow-user', 'mouseover', function (fUser) {
            var span = sz('span', fUser)[0];
            if (span) span.style.color = 'White';
        });        
        
        /***********************************
        * list of circle names to share the post
        ***********************************/
        dq.bind('.circle-name', 'mouseover', function (cName) {
            var span = sz('span', cName)[0];
            if (span) span.style.color = 'White';
        });
        dq.bind('.circle-name', 'mouseout', function (cName) {
            var span = sz('span', cName)[0];
            if (span) span.style.color = 'Gray';
        });
    };

    /***********************************
    * Handling all events/stuff needed for user-page
    ***********************************/
    var handleEvents = function () {
        menuClick();
        newTweet();         /* click one the "Share" button for new post/tweet */
        postOptions();      /* Edit/Delete or link-to-post options */
        addMoreClick();     /* add circles/users to share the post */
        mouseoverEvents();  /* Mouse over/out events handler */

        /***********************************
        * If user is in the circles, then show green-box [As Google+ shows red-button when user is not in-circles and green-button when user is in-circles]
        ***********************************/
        var incircle = dq.find('#in-circle');
        if (incircle && incircle.value == 'true') {
            var followUser = dq.find('#follow-user');

            followUser.className = 'green-button';
            dq.find('span', followUser)[0].innerHTML = 'In Circle';
        }

        /***********************************
        * Post can be long, so enabling textarea expand dynamically
        ***********************************/
        var tweetBox = dq.find('#tweetMessage');
        if (tweetBox) expand(tweetBox);

        /***********************************
        * Formatting codes on the page because user don't care to insert formatted code
        ***********************************/
        var pre = dq.find('pre');
        dq.each(pre, function (code) {
            /* Formatting all codes */
            var jsDecoder = new JsDecoder();
            jsDecoder.s = code.textContent;
            code.innerHTML = jsDecoder.decode();
        });
    };

    return {
        /***********************************
        * Its job is to handle the whole stuff needed on the page
        ***********************************/
        handleEvents: function () {
            return handleEvents();
        },

        /***********************************
        * Outside the file we can also call other textareas to be auto-expanded
        ***********************************/
        expand: function (elemeToExpand) {
            return expand(elemeToExpand);
        }
    };
})(user);